![PyPI Now Supports iOS and Android Wheels for Mobile Python Development](https://cdn.sanity.io/images/cgdhsj6q/production/96416c872705517a6a65ad9646ce3e7caef623a0-1024x1024.webp?w=400&fit=max&auto=format)
Security News
PyPI Now Supports iOS and Android Wheels for Mobile Python Development
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Errors with superpowers.
npm install --save incident
instanceof Error
tests.Ensure that each of you always provide a name
. You should mainly look for new Incident(message)
and
new Incident(cause, message)
which would be interpreted as new Incident(name)
and new Incident(cause, name)
in version 3.
Also note that the order of the generic parameters changed from <Name, Data, Cause>
to <Data, Name, Cause>
.
My goal with this library was to simplify the automatic handling of errors and
provide better error messages. Javascript errors are not very helpful because extending
them and then extracting data is tedious because you need a declaration statement,
multiple assignations, and then match on the name that is usually the generic "Error"
or rely on a brittle instance of
.
To achieve automatic error handling, the information describing the error should
be easily accessible programmatically. That's why you can directly pass a data object
to the Incident
constructor. Being able to pass data on the fly means that you do not need a
declaration statement for the error separate property assignations. A key identifying the error
is the second requirement for automatic error handling, Incident
simply uses the name.
As explained in the features, it allows to unambiguously identify the error (I'd recommend to
always use a name). Using a name (as a string enum variant) is also more reliable than using
instance of
(prototype chain lookup) to check for the type of custom errors. The two main
advantages are that it's easier to serialize / deserialize and is not affected by the module
duplication of the Node module resolution algorithm.
To provide better error messages, especially for asynchronous operations, I made the cause of the error a first-class information. It allows to deal with deferred or wrapped errors more pleasant: the stack trace at each step is preserved.
The library is already pretty verbose (I am waiting for generic defaults in TS 2.3) so
I'd like to keep the usage simple. For example, I have experimented with a arrays of causes (when
an error has multiple simultaneous causes).
The displayed messages were pretty good but it made the code to handle the errors automatically
pretty complex because the type for the cause was Error | Error[] | undefined
.
This feature did not even make it to the version 1. If you need it, but your multiple reasons
in the data
object.
Finally, performance is also a goal. That's why the library performs late / lazy stack capture and allows for message formatters that are called only when needed.
function Incident; // The Incident constructor
interface StaticIncident; // Interface of the constructor
interface Incident; // Interface of the instance
Incident
An Incident
has the following interface:
interface Incident<
Data extends object,
Name extends string = string,
Cause extends (Error | undefined) = (Error | undefined)
> extends Error {
name: Name;
message: string;
data: Data;
cause: Cause;
stack: string;
toString(): string;
}
typeof data === "object"
undefined
if there is no cause.name
A name uniquely identifying the error. Displayed at the top of the stack.
message
A debug message for developers describing the error. Displayed at the top of the stack.
If you provide data
but no message
, the message will be generate from the data using
object-inspect with default options.
data
A data object associated to the error. This should describe the error enough to handle it programmatically.
cause
A previous error that cause this error. This usually has more detail about what happened.
stack
The error stack of the incident. Contains the standard stack frames, and the stack of the cause if there is any.
new Incident<Data, Name, Cause>([cause,] name, [data,] [message]);
You can pass almost any combination of parameters you want as long as it is in the
right order (see table below for the details) and a name is specified. If you want
to explicitly define the generic parameters, you don't have to define the generic
parameter for a function parameter you do not use. Instanciating a new Incident
instance will perform a lazy capture of the current call stack (only resolved when
reading .stack
or throwing the error).
cause
Cause
cause
, Cause extends Error
else Cause
is undefined
.undefined
undefined
name
Name
Name extends string
string
data
Data
Data extends object
object
{}
message
string | ((data?: typeof data) => string)
""
message
property is accessedstack
property is accessednew
operator signatures table
cause | name | data | message | Comment |
---|---|---|---|---|
✔ | new<Name>(...): Incident<Name, object, undefined> | |||
✔ | ✔ | new<Name>(...): Incident<Name, object, undefined> | ||
✔ | ✔ | new<Data, Name>(...): Incident<Name, Data, undefined> | ||
✔ | ✔ | ✔ | new<Data, Name>(...): Incident<Name, Data, undefined> | |
✔ | ✔ | new<Name, Cause>(...): Incident<Name, object, Cause> | ||
✔ | ✔ | ✔ | new<Name, Cause>(...): Incident<Name, object, Cause> | |
✔ | ✔ | ✔ | new<Data, Name, Cause>(...): Incident<Name, Data, Cause> | |
✔ | ✔ | ✔ | ✔ | new<Data, Name, Cause>(...): Incident<Name, Data, Cause> |
You can call Incident
as a simple function. It has the same signature as
the new
operator but does not capture the stack. You may want to use
it for higher order errors, but I recommend to capture the stack for root causes.
The simple call also supports the additional signature (cause: Error)
.
This will perform a conversion from any error to an instance of the currently called
Incident. You can use it normalize simple errors to Incident or mitigate module
duplication if you rely on instanceof
. The resulting incident will have the
same name, message, stack and data. If the input error was an Incident with
a lazy message or stack, it will remain non-evaluated.
If the argument is already an instance of the current Incident
, a copy will be
created. If you added extra properties, they will be lost.
cause | name | data | message | Comment |
---|---|---|---|---|
✔ | Converts to an instance of this Incident constructor | |||
✔ | <Name>(...): Incident<Name, object, undefined> | |||
✔ | ✔ | <Name>(...): Incident<Name, object, undefined> | ||
✔ | ✔ | <Data, Name>(...): Incident<Name, Data, undefined> | ||
✔ | ✔ | ✔ | <Data, Name>(...): Incident<Name, Data, undefined> | |
✔ | ✔ | <Name, Cause>(...): Incident<Name, object, Cause> | ||
✔ | ✔ | ✔ | <Name, Cause>(...): Incident<Name, object, Cause> | |
✔ | ✔ | ✔ | <Data, Name, Cause>(...): Incident<Name, Data, Cause> | |
✔ | ✔ | ✔ | ✔ | <Data, Name, Cause>(...): Incident<Name, Data, Cause> |
// Example of type resolution on a discriminated type
import Incident from "incident";
// Associate the name "SyntaxError" to {index: number}
type SyntaxError = Incident<"SyntaxError", {index: number}, undefined>;
// Associate the name "TypeError" to {typeName: string}
type TypeError = Incident<"TypeError", {typeName: string}, undefined>;
// Created a discriminated type
type BaseError = SyntaxError | TypeError;
// Example usage accepting the discriminated type
function printError(error: BaseError): void {
// Switch on the discriminant
switch (error.name) {
case "SyntaxError":
// No need to cast: successfully resolved to SyntaxError
const index: number = error.data.index;
console.log(`Received a syntax error with index: ${index}`);
break;
case "TypeError":
// Successfully resolved to TypeError
const typename: string = error.data.typeName;
console.log(`Received a type error with typename: ${typename}`);
break;
}
}
FAQs
Errors with superpowers
The npm package incident receives a total of 47 weekly downloads. As such, incident popularity was classified as not popular.
We found that incident demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.